package edu.uoc.tds.server;


import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.sql.PreparedStatement;
import java.util.Date;
import edu.uoc.tds.common.UtilLenguaje;
import javax.swing.JOptionPane;


/*******************************************************************************
* Propósito: Obtener datos de la BBDD relativos a las inscripciones
* @author Fco. Javier González
* @version 1.0
*******************************************************************************/
public class GestorInscripcion
{

    private Connection conexion = null;


    //Constructor
    public GestorInscripcion(Connection con)
    {
	this.conexion = con;
    }


    /***************************************************************************
    *
    * Devuelve la conexión actual a la base de datos
    *
    * @return Conexion actual con la base de datos
    *
    ***************************************************************************/
    public Connection getConnection()
    {
	return this.conexion;
    }


    /***************************************************************************
    * Devuelve los contenidos de la consulta de eventos en una fecha concreta
    * y con un filtro de tipo de evento
    *
    * @param Date fecha La fecha deseada para buscar el evento.
    * @param String tipoEvento El tipo evento que selecciona el usuario en el
    * combo de filtrado
    * @return ArrayList<Object[]> El resultado de la consulta
    ***************************************************************************/
    public ArrayList<Object[]> getEventosIns (Date fecha, String tipoEvento) throws SQLException
    {

        ArrayList<Object[]> lista = new ArrayList<Object[]>();
        PreparedStatement sentencia = null;
        ResultSet rs= null;
        Object [] c = null;

        try
        {
            //Almacenamos en un string la select que queremos realizar
            String query ="";

            if (tipoEvento.equals("Todos los eventos"))
            {
                    query = " select e.id_evento as id, te.descripcion as tipo, co.localidad as localidad," +
                            " u.nombre as universidad, e.nombre as nombre from evento e, " +
                            " universidad u, tipoevento te, centrodocente c, contacto co" +
                            " where e.id_tipo_evento = te.id_tipo_evento and u.id_universidad = e.id_universidad and" +
                            " e.id_centro = c.id_centro and c.id_contacto = co.id_contacto and" +
                            " e.fecha_inicio = ?" +
                            " order by tipo, localidad, universidad, nombre";

            }

            else
            {

                    query = " select e.id_evento as id, te.descripcion as tipo, co.localidad as localidad," +
                            " u.nombre as universidad, e.nombre as nombre from evento e, " +
                            " universidad u, tipoevento te, centrodocente c, contacto co" +
                            " where e.id_tipo_evento = te.id_tipo_evento and u.id_universidad = e.id_universidad and" +
                            " e.id_centro = c.id_centro and c.id_contacto = co.id_contacto and" +
                            " e.fecha_inicio = ? and te.descripcion = ?" +
                            " order by tipo, localidad, universidad, nombre";

            }


            //PreparedStatment con esa query
            sentencia = getConnection().prepareStatement(query);

            if (tipoEvento.equals("Todos los eventos"))
            {
                 //Los parámetros en la query
                sentencia.setDate(1, new java.sql.Date(fecha.getTime()));
            }
            else
            {
                //Los parámetros en la query
                sentencia.setDate(1, new java.sql.Date(fecha.getTime()));
                sentencia.setString(2, tipoEvento);
            }

            //Resulset con los resultados de la consulta
            rs = sentencia.executeQuery();

            while (rs.next())
            {
                c = new Object[5];

                c[0] = rs.getInt("id");
                c[1] = rs.getString("tipo");
                c[2] = rs.getString("localidad");
                c[3] = rs.getString("universidad");
                c[4] = rs.getString("nombre");

                lista.add(c);
            }

        }

        catch(SQLException e)
        {

            //Error al realizar la Select
            JOptionPane.showMessageDialog(null, UtilLenguaje.getMessage("err.sql"), UtilLenguaje.getMessage("gInsc")
            ,JOptionPane.ERROR_MESSAGE);

        }
	catch (Exception e)
        {

            //Error indeterminado
            JOptionPane.showMessageDialog(null, UtilLenguaje.getMessage("err.in"), UtilLenguaje.getMessage("gInsc")
            ,JOptionPane.ERROR_MESSAGE);

	}

        //Cerramos el recordset y el statement
        finally
        {

            if (rs != null) rs.close();
            if (sentencia != null) sentencia.close();

        }

        return lista;
    }

    /***************************************************************************
    * Devuelve los contenidos de la consulta de detalles de un evento
    *
    * @param int idEvento El id del evento del que se quieren mostrar los detalles
    * @return ArrayList<Object[]> El resultado de la consulta
    ***************************************************************************/
    public ArrayList<Object[]> getDetallesEventoIns (int idEvento) throws SQLException
    {

        ArrayList<Object[]> lista = new ArrayList<Object[]>();
        PreparedStatement sentencia = null;
        ResultSet rs= null;
        Object [] c = null;

        //Almacenamos en un string la select que queremos realizar
        String query ="";

        try
        {
            //Almacenamos en un string la select que queremos realizar
            query = " select te.descripcion as tipo, e.nombre as nombre, " +
                    " u.nombre as universidad, c.nombre as centro, domicilio, localidad," +
                    " precio, plazas, plazas - (select count(*) from inscripcion i where" +
                    " i.id_evento= e.id_evento) as pLibres, duracion from " +
                    " evento e" +
                    " INNER JOIN universidad AS u ON (u.id_universidad = e.id_universidad)" +
                    " INNER JOIN tipoevento AS te ON (e.id_tipo_evento = te.id_tipo_evento)" +
                    " INNER JOIN centrodocente AS c ON (e.id_centro = c.id_centro) " +
                    " INNER JOIN contacto ON (contacto.id_contacto = c.id_contacto)" +
                    " where e.id_evento=?";

            //PreparedStatment con esa query
            sentencia = getConnection().prepareStatement(query);

            //Parámetro de la query
            sentencia.setInt(1, idEvento);

            //Resulset con los resultados de la consulta
            rs = sentencia.executeQuery();

            while (rs.next())
            {
                c = new Object[10];

                c[0] = rs.getString("tipo");
                c[1] = rs.getString("nombre");
                c[2] = rs.getString("universidad");
                c[3] = rs.getString("centro");
                c[4] = rs.getString("localidad");
                c[5] = rs.getString("domicilio");
                c[6] = rs.getInt("duracion");
                c[7] = rs.getDouble("precio");
                c[8] = rs.getInt("plazas");
                c[9] = rs.getInt("pLibres");


                lista.add(c);
            }

        }

        catch(SQLException e)
        {
            //Error al realizar la Select
            JOptionPane.showMessageDialog(null, UtilLenguaje.getMessage("err.sql"), UtilLenguaje.getMessage("gInsc")
            ,JOptionPane.ERROR_MESSAGE);

        }
	catch (Exception e)
        {

            //Error indeterminado
            JOptionPane.showMessageDialog(null, UtilLenguaje.getMessage("err.in"), UtilLenguaje.getMessage("gInsc")
            ,JOptionPane.ERROR_MESSAGE);

	}

        //Cerramos el recordset y el statement
        finally
        {

            if (rs != null) rs.close();
            if (sentencia != null) sentencia.close();

        }

        return lista;
    }

    /***************************************************************************
    * Devuelve los datos de los prerrequisitos de un evento cuyo id_evento se
    * pasa como parámetro
    *
    * @param int idEvento El id del evento del que se quieren mostrar los
    * prerrequisitos
    * @return ArrayList<Object[]> El resultado de la consulta
    ***************************************************************************/
    public ArrayList<Object[]> getPrerrequisitosIns (int idEvento) throws SQLException
    {

        ArrayList<Object[]> lista = new ArrayList<Object[]>();
        PreparedStatement sentencia = null;
        ResultSet rs= null;
        Object [] c = null;

        //Almacenamos en un string la select que queremos realizar
        String query ="";

        try
        {
            //Almacenamos en un string la select que queremos realizar
            query = " select" +
                    " (select te.descripcion from evento e, prerrequisitos f," +
                    " tipoevento te  where e.id_evento = f.id_eventoprerequisito " +
                    " and f.id_eventoprerequisito = p.id_eventoprerequisito and" +
                    " e.id_tipo_evento = te.id_tipo_evento group by te.descripcion)as tipo, " +
                    " (select nombre from evento e, prerrequisitos " +
                    " f where e.id_evento = f.id_eventoprerequisito and " +
                    " f.id_eventoprerequisito = p.id_eventoprerequisito " +
                    " group by nombre)as nombreRequisito, " +
                    " (select u.nombre from evento e, prerrequisitos f, universidad u " +
                    " where e.id_evento = f.id_eventoprerequisito and  f.id_eventoprerequisito =" +
                    " p.id_eventoprerequisito and e.id_universidad = u.id_universidad " +
                    " group by u.nombre) as universidad " +
                    " from prerrequisitos p, evento e where e.id_evento = " +
                    " p.id_evento and e.id_evento = ? " +
                    " group by p.id_eventoprerequisito";

            //PreparedStatment con esa query
            sentencia = getConnection().prepareStatement(query);

            //Parámetro de la query
            sentencia.setInt(1, idEvento);

            //Resulset con los resultados de la consulta
            rs = sentencia.executeQuery();

            while (rs.next())
            {
                c = new Object[3];

                c[0] = rs.getString("tipo");
                c[1] = rs.getString("nombreRequisito");
                c[2] = rs.getString("universidad");


                lista.add(c);
            }

        }

        catch(SQLException e)
        {

            //Error al realizar la Select
            JOptionPane.showMessageDialog(null, UtilLenguaje.getMessage("err.sql"), UtilLenguaje.getMessage("gInsc")
            ,JOptionPane.ERROR_MESSAGE);

        }
	catch (Exception e)
        {

            //Error indeterminado
            JOptionPane.showMessageDialog(null, UtilLenguaje.getMessage("err.in"), UtilLenguaje.getMessage("gInsc")
            ,JOptionPane.ERROR_MESSAGE);

	}

        //Cerramos el recordset y el statement
        finally
        {

            if (rs != null) rs.close();
            if (sentencia != null) sentencia.close();

        }

        return lista;
    }


    /***************************************************************************
    * Devuelve el número de eventos que son prerrequisitos y a los que ha
    * asistido el usuario
    *
    * @param int idUsuario El id del usuario del que se quieren mostrar los
    * prerrequisitos
    * @return ArrayList<Object[]> El resultado de la consulta
    ***************************************************************************/
    public int getPrerrequisitosAsistidosIns (int id_evento, String idUsuario) throws SQLException
    {

        int valor=0;
        PreparedStatement sentencia = null;
        ResultSet rs= null;


        //Almacenamos en un string la select que queremos realizar
        String query ="";

        try
        {
            //Almacenamos en un string la select que queremos realizar
            query = " select count(*) as numero from prerrequisitos p, evento e where"+
                    " p.id_evento = e.id_evento and e.id_evento = ? and"+
                    " id_eventoprerequisito in (select id_evento from inscripcion"+
                    " where codigo = ?)";

            //PreparedStatment con esa query
            sentencia = getConnection().prepareStatement(query);

            //Parámetro de la query
            sentencia.setInt(1, id_evento);
            sentencia.setString(2, idUsuario);

            //Resulset con los resultados de la consulta
            rs = sentencia.executeQuery();

            while (rs.next())
            {
                 valor = rs.getInt("numero");
            }

        }

        catch(SQLException e)
        {

            //Error al realizar la Select
            JOptionPane.showMessageDialog(null, UtilLenguaje.getMessage("err.sql"), UtilLenguaje.getMessage("gInsc")
            ,JOptionPane.ERROR_MESSAGE);


        }
	catch (Exception e)
        {

            //Error indeterminado
            JOptionPane.showMessageDialog(null, UtilLenguaje.getMessage("err.in"), UtilLenguaje.getMessage("gInsc")
            ,JOptionPane.ERROR_MESSAGE);

	}

        //Cerramos el recordset y el statement
        finally
        {

            if (rs != null) rs.close();
            if (sentencia != null) sentencia.close();

        }

        return valor;
    }


    /***************************************************************************
    * Devuelve el número de eventos a los que el usuario se ha inscrito en una
    * fecha concreta
    *
    * @param String idUsuario El id del usuario
    * @param Date fecha La fecha en la que se quiere realizar la consulta
    * @return int El resultado de la consulta
    ***************************************************************************/
    public int getInscritosFecha(String userId, Date fecha) throws SQLException
    {

        int valor=0;
        PreparedStatement sentencia = null;
        ResultSet rs= null;


        //Almacenamos en un string la select que queremos realizar
        String query ="";

        try
        {
            //Almacenamos en un string la select que queremos realizar
            query = " select count(*) as numero from inscripcion i, evento e " +
                    " where i.id_evento = e.id_evento and fecha_inicio = ? " +
                    " and codigo = ?";

            //PreparedStatment con esa query
            sentencia = getConnection().prepareStatement(query);

            //Parámetro de la query
            sentencia.setDate(1, new java.sql.Date(fecha.getTime()));
            sentencia.setString(2, userId);

            //Resulset con los resultados de la consulta
            rs = sentencia.executeQuery();

            while (rs.next())
            {
                 valor = rs.getInt("numero");
            }

        }

        catch(SQLException e)
        {


            //Error al realizar la Select
            JOptionPane.showMessageDialog(null, UtilLenguaje.getMessage("err.sql"), UtilLenguaje.getMessage("gInsc")
            ,JOptionPane.ERROR_MESSAGE);

        }
	catch (Exception e)
        {


            //Error indeterminado
            JOptionPane.showMessageDialog(null, UtilLenguaje.getMessage("err.in"), UtilLenguaje.getMessage("gInsc")
            ,JOptionPane.ERROR_MESSAGE);

	}

        //Cerramos el recordset y el statement
        finally
        {
            if (rs != null) rs.close();
            if (sentencia != null) sentencia.close();
        }

        return valor;
    }

    /***************************************************************************
    * Devuelve el nombre y datos bancarios de un usuario que se pasa como
    * parámetro si el parámtro valor es true.
    *
    * Únicamente los datos si es false.
    *
    * @param String idUsuario El id del usuario
    * @param  boolean valor Para saber que se debe devolver
    * @return ArrayList<Object[]> El resultado de la consulta
    ***************************************************************************/
    public ArrayList<Object[]> getDatosIns (String idUsuario, boolean valor) throws SQLException
    {

        ArrayList<Object[]> lista = new ArrayList<Object[]>();
        PreparedStatement sentencia = null;
        ResultSet rs= null;
        Object [] c = null;

        //Almacenamos en un string la select que queremos realizar
        String query ="";


        try
        {

            if (valor == true)
            {
                //Almacenamos en un string la select que queremos realizar
                query = "select nombre, apellidos, banco, sucursal, dc, cc from " +
                        "usuario u, datosbancarios d where codigo=? and " +
                        "u.id_datos_bancarios =  d.id_datos_bancarios  ";
            }

            else
            {
                //Almacenamos en un string la select que queremos realizar
                query = "select nombre, apellidos from " +
                        "usuario where codigo= ? ";

            }


            //PreparedStatment con esa query
            sentencia = getConnection().prepareStatement(query);

            //Parámetro de la query
            sentencia.setString(1, idUsuario);

            //Resulset con los resultados de la consulta
            rs = sentencia.executeQuery();

            if (valor == true)
            {

                while (rs.next())
                {
                    c = new Object[6];

                    c[0] = rs.getString("nombre");
                    c[1] = rs.getString("apellidos");
                    c[2] = rs.getString("banco");
                    c[3] = rs.getString("sucursal");
                    c[4] = rs.getString("dc");
                    c[5] = rs.getString("cc");
                    lista.add(c);
                }
            }

            else
            {

                while (rs.next())
                {
                    c = new Object[2];

                    c[0] = rs.getString("nombre");
                    c[1] = rs.getString("apellidos");

                    lista.add(c);
                }
            }

        }

        catch(SQLException e)
        {

            //Error al realizar la Select
            JOptionPane.showMessageDialog(null, UtilLenguaje.getMessage("err.sql"), UtilLenguaje.getMessage("gInsc")
            ,JOptionPane.ERROR_MESSAGE);

        }
	catch (Exception e)
        {

            //Error indeterminado
            JOptionPane.showMessageDialog(null, UtilLenguaje.getMessage("err.in"), UtilLenguaje.getMessage("gInsc")
            ,JOptionPane.ERROR_MESSAGE);

	}

        //Cerramos el recordset y el statement
        finally
        {

            if (rs != null) rs.close();
            if (sentencia != null) sentencia.close();

        }

        return lista;
    }


    /***************************************************************************
    * Inserta una nueva inscripción
    *     *
    * @param String idUsuario El id del usuario que se inscribe
    * @param int idEvento El id del evento en el que se inscribe
    * @param Date fecha La fecha en la que se inscribe
    ***************************************************************************/

    public void altaInscripcionIns(String userId, int idEvento, Date fecha) throws SQLException
    {


        PreparedStatement sentencia = null;
        String query ="";

        try
        {

            //Almacenamos en un string la select que queremos realizar
            query= " INSERT INTO inscripcion (codigo, id_evento, " +
                   " fecha_inscripcion, check_in) VALUES (?,?,?, false)";

            //PreparedStatment con esa query
            sentencia = getConnection().prepareStatement(query,ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_UPDATABLE);

            //Parámetros de la query
            sentencia.setString(1,userId);
            sentencia.setInt(2,idEvento);
            sentencia.setDate(3, new java.sql.Date(fecha.getTime()));

            //Ejecuta la sentencia
            sentencia.execute();

	}
        catch(SQLException e)
        {
           
            //Error al realizar la Select
            JOptionPane.showMessageDialog(null, UtilLenguaje.getMessage("err.sql"), UtilLenguaje.getMessage("gInsc")
            ,JOptionPane.ERROR_MESSAGE);

        }
	catch (Exception e)
        {


            //Error indeterminado
            JOptionPane.showMessageDialog(null, UtilLenguaje.getMessage("err.in"), UtilLenguaje.getMessage("gInsc")
            ,JOptionPane.ERROR_MESSAGE);

	}

        //Cerramos el statement
        finally
        {

            if (sentencia != null) sentencia.close();

        }

    }

    /***************************************************************************
    * Devuelve los contenidos de la consulta de histórico de inscripciones
    *
    * @param String idUsuario El id del usuario para el que se quiere consultar
    * @param Date desde
    * @param Date hasta
    * @param String tipo El tipo de evento
    * @return ArrayList<Object[]> El resultado de la consulta
    ***************************************************************************/
    public ArrayList<Object[]> getHistoricoIns (String idUsuario, Date desde, Date hasta, Date actual, String tipo) throws SQLException
    {

        ArrayList<Object[]> lista = new ArrayList<Object[]>();
        PreparedStatement sentencia = null;
        ResultSet rs= null;
        Object [] c = null;

        //Almacenamos en un string la select que queremos realizar
        String query ="";

        try
        {

            if (tipo.equalsIgnoreCase("Todos los eventos"))
            {

                //Almacenamos en un string la select que queremos realizar
                query = " select e.id_evento as id, u.nombre as universidad, c.nombre as centro, " +
                    " e.nombre as nombre, te.descripcion as tipo, fecha_inicio, " +
                    " fecha_fin, (fecha_inicio - ?) as topeInf, (fecha_inicio + " +
                    "duracion -1 - ?) as topeSup, check_in from evento e, universidad u, tipoevento" +
                    " te, centrodocente c, inscripcion i where e.id_tipo_evento " +
                    " = te.id_tipo_evento and u.id_universidad = e.id_universidad and " +
                    " e.id_centro = c.id_centro and e.id_evento = i.id_evento and" +
                    " i.codigo = ? and fecha_inicio between ? and ?";

                    //PreparedStatment con esa query
                    sentencia = getConnection().prepareStatement(query);

                    //Parámetro de la query
                    sentencia.setDate(1, new java.sql.Date(actual.getTime()));
                    sentencia.setDate(2, new java.sql.Date(actual.getTime()));
                    sentencia.setString(3, idUsuario);
                    sentencia.setDate(4, new java.sql.Date(desde.getTime()));
                    sentencia.setDate(5, new java.sql.Date(hasta.getTime()));
            }

            //Se selecciona un tipo de evento en el combo
            else
            {

                //Almacenamos en un string la select que queremos realizar
                query = "select e.id_evento as id, u.nombre as universidad, c.nombre as centro, " +
                    " e.nombre as nombre, te.descripcion as tipo, fecha_inicio, " +
                    " fecha_fin, (fecha_inicio - ?) as topeInf, (fecha_inicio + " +
                    "duracion -1 - ?) as topeSup, check_in from evento e, universidad u, tipoevento" +
                    " te, centrodocente c, inscripcion i where e.id_tipo_evento " +
                    " = te.id_tipo_evento and u.id_universidad = e.id_universidad and " +
                    " e.id_centro = c.id_centro and e.id_evento = i.id_evento and" +
                    " i.codigo = ? and fecha_inicio between ? and ? and te.descripcion = ?";

                //PreparedStatment con esa query
                sentencia = getConnection().prepareStatement(query);

                //Parámetro de la query
                sentencia.setDate(1, new java.sql.Date(actual.getTime()));
                sentencia.setDate(2, new java.sql.Date(actual.getTime()));
                sentencia.setString(3, idUsuario);
                sentencia.setDate(4, new java.sql.Date(desde.getTime()));
                sentencia.setDate(5, new java.sql.Date(hasta.getTime()));
                sentencia.setString(6, tipo);
            }

            //Resulset con los resultados de la consulta
            rs = sentencia.executeQuery();

            while (rs.next())
            {
                c = new Object[10];

                c[0] = rs.getInt("id");
                c[1] = rs.getString("universidad");
                c[2] = rs.getString("centro");
                c[3] = rs.getString("nombre");
                c[4] = rs.getString("tipo");
                c[5] = rs.getDate("fecha_inicio");
                c[6] = rs.getDate("fecha_fin");
                c[7] = rs.getInt("topeInf");
                c[8] = rs.getInt("topeSup");
                c[9] = rs.getBoolean("check_in");

                lista.add(c);
            }

        }

        catch(SQLException e)
        {


            //Error al realizar la Select
            JOptionPane.showMessageDialog(null, UtilLenguaje.getMessage("err.sql"), UtilLenguaje.getMessage("gInsc")
            ,JOptionPane.ERROR_MESSAGE);

        }
	catch (Exception e)
        {


            //Error indeterminado
            JOptionPane.showMessageDialog(null, UtilLenguaje.getMessage("err.in"), UtilLenguaje.getMessage("gInsc")
            ,JOptionPane.ERROR_MESSAGE);

	}

        //Cerramos el recordset y el statement
        finally
        {

            if (rs != null) rs.close();
            if (sentencia != null) sentencia.close();

        }

        return lista;
    }


    /***************************************************************************
    * Realiza el checkin
    *
    * @param String idUsuario El id del usuario
    * @param int idEvento
    *
    ***************************************************************************/
    public void setCheckin(String idUsuario,int id_evento) throws SQLException
    {

        PreparedStatement sentencia = null;

        //Almacenamos en un string la select que queremos realizar
        String query ="";

        try
        {

            //Almacenamos en un string la select que queremos realizar
            query= " UPDATE inscripcion SET check_in = true WHERE codigo = ? and id_evento = ?";

            //PreparedStatment con esa query
            sentencia = getConnection().prepareStatement(query,ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_UPDATABLE);

            //Parámetros de la query
            sentencia.setString(1,idUsuario);
            sentencia.setInt(2,id_evento);


            //Ejecuta la sentencia
            sentencia.execute();

	}
        catch(SQLException e)
        {


            //Error al realizar la Select
            JOptionPane.showMessageDialog(null, UtilLenguaje.getMessage("err.sql"), UtilLenguaje.getMessage("gInsc")
            ,JOptionPane.ERROR_MESSAGE);

        }
	catch (Exception e)
        {


            //Error indeterminado
            JOptionPane.showMessageDialog(null, UtilLenguaje.getMessage("err.in"), UtilLenguaje.getMessage("gInsc")
            ,JOptionPane.ERROR_MESSAGE);

	}

        //Cerramos el statement
        finally
        {

            if (sentencia != null) sentencia.close();

        }

    }

}